Imports System.Xml
Imports System.Text
Imports System.IO
Imports System.ComponentModel
Imports System.Globalization
Imports Microsoft.Services.BizTalkApplicationFramework.BizUnit

<CLSCompliant (True)> _
Public Class Main

#Region "Private Varaiables"

    Private smokeTestLevel As TestLevel
    Private smokeTestStepNode As Integer

    Private editMode As Boolean
    Private m_IsDirty As Boolean
    Private errorCaught As Boolean
    Private testsRunning As Boolean
    Private testType As RunTestType
    Private smokeTestNode As TreeNode
    Private textWriter As TextBoxWriter
    Private resultsFolder As String = String.Empty
    Private sourceSmokeTestPath As String = String.Empty

#End Region

#Region "Private Constants"

    Private Const edit As String = "EDIT"
    Private Const testSetupKey As String = "Test Setup"
    Private Const testExecutionKey As String = "Test Execution"
    Private Const testCleanUpKey As String = "Test Cleanup"

    Private Const xmlFileSearchPattern As String = "*.xml"
    Private Const noXMLResults As String = "No results available at present"

#End Region

#Region "Private Structures"

    Private Structure NodeInformation
        Dim xmlDoc As XmlDocument
        Dim testResults As StringBuilder
    End Structure

    Private Structure BizUnitInformation
        Dim testResults As StringBuilder
        Dim testScriptNode As XmlNode
    End Structure

#End Region

#Region "Private Enums"

    Private Enum TestLevel
        None = 0
        Setup = 1
        Execution = 2
        CleanUp = 3
    End Enum

    Private Enum FormImages
        Save = 0
        Copy = 1
        Success = 2
        Failed = 3
        Intermediate = 4
        Script = 5
        Running = 6
    End Enum

    Private Enum RunTestType
        [Single] = 0
        All = 1
    End Enum

#End Region

#Region "Private Delegates"

    Private Delegate Sub ChangeTab1 (ByVal tp As TabPage)

    Private Delegate Function GetSelectedNode1() As TreeNode

    Private Delegate Sub UpdateOutputText1 (ByVal value As String)

    Private Delegate Sub GenericSingleBooleanDelegate (ByVal value As Boolean)

    Private Delegate Sub GenericSingleTreeNodeDelegate (ByVal node As TreeNode)

    Private Delegate Sub UpdateImageIndex1 (ByVal testStepNode As TreeNode, ByVal index As FormImages)

#End Region

#Region "Private Control Events"

    Private Sub btnRunAll_Click (ByVal sender As Object, ByVal e As EventArgs) Handles btnRunAll.Click

        testType = RunTestType.All
        bgTestRunner.RunWorkerAsync()

    End Sub

    Private Sub btnRunTest_Click (ByVal sender As Object, ByVal e As EventArgs) Handles btnRunTest.Click
        If GetSelectedNodeIsXMLTest() Then
            testType = RunTestType.Single
            RunTest()
        End If
    End Sub

    Private Sub chkAutoScroll_CheckedChanged (ByVal sender As Object, ByVal e As EventArgs) _
        Handles chkAutoScroll.CheckedChanged
        Common.WriteRegistry ("AutoScroll", chkAutoScroll.Checked.ToString (CultureInfo.InvariantCulture))
    End Sub

    Private Sub chkDisplayErrors_CheckedChanged (ByVal sender As Object, ByVal e As EventArgs) _
        Handles chkDisplayErrors.CheckedChanged
        Common.WriteRegistry ("DisplayErrors", chkDisplayErrors.Checked.ToString (CultureInfo.InvariantCulture))
    End Sub

    Private Sub contextMenuCopy_Click (ByVal sender As Object, ByVal e As EventArgs) Handles contextMenuCopy.Click
        tsCopyAll_Click (Me, Nothing)
    End Sub

    Private Sub contextMenuEdit_Click (ByVal sender As Object, ByVal e As EventArgs) Handles contextMenuEdit.Click
        editMode = True
        tsLabel2.Text = edit
        txtBizUnitTestDetail.ReadOnly = False
        txtBizUnitTestDetail.Focus()
    End Sub

    Private Sub contextMenuLoad_Click (ByVal sender As Object, ByVal e As EventArgs) Handles contextMenuLoad.Click
        tsLoad_Click (Me, Nothing)
    End Sub

    Private Sub contextMenuSave_Click (ByVal sender As Object, ByVal e As EventArgs) Handles contextMenuSave.Click
        tsSave_Click (Me, Nothing)
    End Sub

    Private Sub contextMenuUnload_Click (ByVal sender As Object, ByVal e As EventArgs) Handles contextMenuUnload.Click
        Dim smokeTestPath As String = String.Empty

        tvSmokeTests.Nodes.Remove (tvSmokeTests.SelectedNode)
        tvSmokeTests.Refresh()

        For i As Integer = 0 To tvSmokeTests.Nodes.Count - 1
            smokeTestPath &= tvSmokeTests.Nodes (i).ToString.Remove (0, 9).Trim & ";"
        Next

        Common.WriteRegistry ("SourcePath", smokeTestPath)

    End Sub

    Private Sub frmMain_Load (ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

        Me.Text = Common.formCaption & Space (2) & "Ver: " & My.Application.Info.Version.ToString

        LoadSettings()

        textWriter = New TextBoxWriter (txtBizUnitTestResult)
        AddHandler textWriter.Results, AddressOf TextWriter_Results

        Console.SetOut (textWriter)

    End Sub

    Private Sub TextWriter_Results (ByVal sender As Object, ByVal e As XMLEventArgs)
        Dim nodeInfo As NodeInformation
        Dim smokeTestNode As TreeNode = GetSelectedNode()

        If e.XmlResult.StartsWith (Chr (31) & Chr (8), StringComparison.OrdinalIgnoreCase) Then Exit Sub

        If smokeTestNode.Tag Is Nothing Then
            nodeInfo = New NodeInformation
            nodeInfo.testResults.Append (e.XmlResult.ToString)
        Else
            nodeInfo = DirectCast (smokeTestNode.Tag, NodeInformation)
            If nodeInfo.testResults Is Nothing Then nodeInfo.testResults = New StringBuilder
            nodeInfo.testResults.AppendLine (e.XmlResult.ToString)
        End If

        smokeTestNode.Tag = nodeInfo

        If e.XmlResult.Contains ("Setup Test:") Then
            smokeTestStepNode = - 1
            smokeTestLevel = TestLevel.Setup
        ElseIf e.XmlResult.Contains ("Execute Test:") Then
            smokeTestStepNode = - 1
            smokeTestLevel = TestLevel.Execution
        ElseIf e.XmlResult.Contains ("Tear Down Test:") Then
            smokeTestStepNode = - 1
            smokeTestLevel = TestLevel.CleanUp
        End If

        If smokeTestLevel <> TestLevel.None Then
            Dim testTypeNode As TreeNode = Nothing

            Select Case smokeTestLevel
                Case TestLevel.Setup
                    testTypeNode = smokeTestNode.Nodes (0)
'testSetupKey
                Case TestLevel.Execution
                    testTypeNode = smokeTestNode.Nodes (1)
'testExecutionKey
                Case TestLevel.CleanUp
                    testTypeNode = smokeTestNode.Nodes (2)
'testCleanUpKey
            End Select

            UpdateTestNode (testTypeNode, e.XmlResult)
        End If

    End Sub

    Private Sub tsClear_Click (ByVal sender As Object, ByVal e As EventArgs) Handles tsClear.Click
        txtBizUnitTestDetail.Text = String.Empty
    End Sub

    Private Sub tsCopyAll_Click (ByVal sender As Object, ByVal e As EventArgs) Handles tsCopy.Click
        txtBizUnitTestDetail.SelectAll()
        txtBizUnitTestDetail.Copy()
    End Sub

    Private Sub tsLoad_Click (ByVal sender As Object, ByVal e As EventArgs) Handles tsLoad.Click
        Dim fbd As New FolderBrowserDialog

        With fbd
            .Description = "Please select folder that contains BizUnit tests"
            If sourceSmokeTestPath <> String.Empty Then .SelectedPath = sourceSmokeTestPath
            If .ShowDialog = System.Windows.Forms.DialogResult.OK Then
                sourceSmokeTestPath = .SelectedPath
                tsSave.Enabled = True
                tsCopy.Enabled = True
                tsClear.Enabled = True
                tsRefresh.Enabled = True

                LoadTreeView()

                Dim sourcePaths As String = Common.ReadRegistry ("SourcePath")
                Select Case sourcePaths
                    Case String.Empty : sourcePaths &= sourceSmokeTestPath
                    Case Else : sourcePaths &= ";" & sourceSmokeTestPath
                End Select

                Common.WriteRegistry ("SourcePath", sourcePaths)
            End If
        End With
    End Sub

    ''' <summary>
    ''' Reloads the settings from the App.config
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub tsRefresh_Click (ByVal sender As Object, ByVal e As EventArgs) Handles tsRefresh.Click
        LoadSettings()
        btnRunTest.Enabled = False
        btnRunAll.Enabled = False
    End Sub

    ''' <summary>
    ''' Save the displayed text to a file
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub tsSave_Click (ByVal sender As Object, ByVal e As EventArgs) Handles tsSave.Click

        If GetSelectedNodeIsXMLTest() Then
            SaveFileDialog1.DefaultExt = "*.xml"
            SaveFileDialog1.Filter = "XML File | *.xml|Text File | *.txt"
            Dim dialogResult As DialogResult
            dialogResult = SaveFileDialog1.ShowDialog()
            Select Case dialogResult
                Case dialogResult.OK
                    Dim saveFileStream As Stream = Nothing
                    Try
                        saveFileStream = SaveFileDialog1.OpenFile()
                        Select Case tabOutput.SelectedIndex
                            Case 0 : txtBizUnitTestDetail.SaveFile (saveFileStream, RichTextBoxStreamType.PlainText)
                            Case 1 : txtBizUnitTestResult.SaveFile (saveFileStream, RichTextBoxStreamType.PlainText)
                        End Select
                    Catch ex As IOException
                        MessageBox.Show (ex.Message, Common.formCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning, _
                                         MessageBoxDefaultButton.Button1, MessageBoxOptions.RightAlign)
                    Finally
                        If Not saveFileStream Is Nothing Then
                            saveFileStream.Flush()
                            saveFileStream.Close()
                            saveFileStream = Nothing
                        End If
                    End Try
            End Select
        End If

    End Sub

    Private Sub tvSmokeTests_AfterSelect (ByVal sender As Object, ByVal e As TreeViewEventArgs) _
        Handles tvSmokeTests.AfterSelect
        If Not testsRunning Then
            If GetSelectedNodeIsXMLTest() Then
                btnRunAll.Enabled = False
                btnRunTest.Enabled = Not btnRunAll.Enabled
            Else
                If Not CheckIfNodeIsChildOfTest (GetSelectedNode) Then
                    btnRunAll.Enabled = True
                    btnRunTest.Enabled = Not btnRunAll.Enabled
                Else
                    btnRunAll.Enabled = False
                    btnRunTest.Enabled = False
                End If
            End If
        End If

        Dim xmlDoc As XmlDocument

        If e.Node.Text.Contains (".xml") Then
            If e.Node.Tag Is Nothing Then : LoadTestDefinition (e.Node)
            Else
                Dim nodeInfo As NodeInformation
                nodeInfo = DirectCast (e.Node.Tag, NodeInformation)

                If nodeInfo.testResults Is Nothing Then nodeInfo.testResults = New StringBuilder
                txtBizUnitTestResult.Text = nodeInfo.testResults.ToString

                txtBizUnitTestDetail.Text = PrettyPrintXML (nodeInfo.xmlDoc).ToString
            End If
        Else
            If CheckIfNodeIsChildOfTest (e.Node) Then
                If e.Node.Tag IsNot Nothing Then
                    Dim bizUnitInfo As BizUnitInformation = DirectCast (e.Node.Tag, BizUnitInformation)
                    If bizUnitInfo.testResults Is Nothing Then bizUnitInfo.testResults = New StringBuilder
                    txtBizUnitTestResult.Text = bizUnitInfo.testResults.ToString

                    xmlDoc = New XmlDocument
                    xmlDoc.LoadXml (bizUnitInfo.testScriptNode.OuterXml.ToString)

                    txtBizUnitTestDetail.Text = PrettyPrintXML (xmlDoc).ToString
                End If
            Else
                txtBizUnitTestDetail.Text = String.Empty
                txtBizUnitTestResult.Text = String.Empty
            End If
        End If

    End Sub

    ''' <summary>
    ''' Display a context menu on any node that has a level of 2,3 or 4.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub tvSmokeTests_MouseClick (ByVal sender As Object, ByVal e As MouseEventArgs) _
        Handles tvSmokeTests.MouseClick
        If testsRunning Then Return

        Dim tv As TreeView
        tv = DirectCast (sender, TreeView)

        Select Case e.Button
            Case System.Windows.Forms.MouseButtons.Right
                Dim p As Point
                p = New Point (e.X, e.Y)

                Dim node As TreeNode
                node = tv.GetNodeAt (p)

                If node Is Nothing Then Return

                Dim _oldSelectNode As TreeNode
                _oldSelectNode = tv.SelectedNode

                contextMenuEdit.Visible = False
                contextMenuCopy.Visible = False
                contextMenuSave.Visible = False
                contextMenuRun.Visible = False
                contextMenuSeparator1.Visible = False
                contextMenuRunAll.Visible = False

                If GetSelectedNodeIsXMLTest() Then
                    If tabOutput.SelectedTab Is tabTestDetail Then
                        Select Case node.Level
                            Case 0 'Root Level
                                contextMenuSave.Visible = True
                                ctxMnuEdit.Show (tv, p)
                            Case Else
                                contextMenuEdit.Visible = True
                                contextMenuEdit.Enabled = Not editMode
                                contextMenuCopy.Visible = True
                                contextMenuSave.Visible = True
                                contextMenuSeparator1.Visible = True
                                contextMenuRun.Visible = True
                                ctxMnuEdit.Show (tv, p)
                        End Select
                    ElseIf tabOutput.SelectedTab Is tabTestResult Then
                        contextMenuRun.Visible = True
                        ctxMnuEdit.Show (tv, p)
                    End If
                ElseIf Not CheckIfNodeIsChildOfTest (node) Then
                    Select Case node.Level
                        Case 0 : ctxMenuBizUnitTests.Show (tv, p)
                        Case 1
                            contextMenuRunAll.Visible = True
                            ctxMnuEdit.Show (tv, p)
                    End Select
                Else
                    If tabOutput.SelectedTab Is tabTestDetail Then
                        contextMenuCopy.Visible = True
                        contextMenuEdit.Visible = True
                        ctxMnuEdit.Show (tv, p)
                    End If
                End If
                tv.SelectedNode = _oldSelectNode
                _oldSelectNode = Nothing
            Case System.Windows.Forms.MouseButtons.Left
                If Not txtBizUnitTestDetail.ReadOnly Then
                    txtBizUnitTestDetail.ReadOnly = True
                    tsLabel2.Text = String.Empty
                End If
        End Select

    End Sub

    Private Sub txtOutput_LostFocus (ByVal sender As Object, ByVal e As EventArgs) _
        Handles txtBizUnitTestDetail.LostFocus
        If Not txtBizUnitTestDetail.ReadOnly Then
            Try
                If m_IsDirty Then
                    If _
                        MessageBox.Show ("Changes have been detected. do you wish to save them before continuing?", _
                                         Common.formCaption, MessageBoxButtons.YesNo, MessageBoxIcon.Question, _
                                         MessageBoxDefaultButton.Button1, MessageBoxOptions.RightAlign) = _
                        System.Windows.Forms.DialogResult.Yes Then

                        Dim currentNode As TreeNode
                        currentNode = GetSelectedNode()

                        If GetSelectedNodeIsXMLTest() Then

                            Dim xmlDoc As New XmlDocument
                            Dim smokeTestNode As TreeNode = FindSmokeTestNodeFromChildNode (currentNode)

                            If IsFileReadOnly (smokeTestNode.FullPath) Then
                                tsLabel2.Text = String.Empty
                                Exit Sub
                            End If

                            Try
                                xmlDoc.LoadXml (txtBizUnitTestDetail.Text)
                                xmlDoc.Save (smokeTestNode.FullPath)
                                LoadTestDefinition (smokeTestNode)
                            Catch ex As XmlException
                                Common.LogError (ex.Message.ToString, chkDisplayErrors.Checked)
                                txtBizUnitTestDetail.Focus()
                                Exit Sub
                            Finally : xmlDoc = Nothing
                            End Try
                        ElseIf CheckIfNodeIsChildOfTest (currentNode) Then
                            Dim bizUnitInfo As BizUnitInformation = DirectCast (currentNode.Tag, BizUnitInformation)

                            Dim xmlDoc As New XmlDocument
                            Try
                                Dim oldXMLNode As XmlNode = bizUnitInfo.testScriptNode

                                xmlDoc.LoadXml (txtBizUnitTestDetail.Text)
                                Dim newXMLNode As XmlNode = xmlDoc.LastChild
                                bizUnitInfo.testScriptNode = newXMLNode
                                currentNode.Tag = bizUnitInfo

                                Dim smokeTestNode As TreeNode = FindSmokeTestNodeFromChildNode (currentNode)

                                If IsFileReadOnly(smokeTestNode.FullPath) Then Exit Sub

                                SaveXMLToFile(smokeTestNode, newXMLNode, oldXMLNode)
                            Catch ex As XmlException
                                Common.LogError(ex.Message.ToString, chkDisplayErrors.Checked)
                                txtBizUnitTestDetail.Focus()
                                Exit Sub
                            Finally : xmlDoc = Nothing
                            End Try
                        End If
                    Else
                        Dim node As TreeNode = GetSelectedNode()
                        If GetSelectedNodeIsXMLTest() Then
                            Dim nodeInfo As NodeInformation = DirectCast (node.Tag, NodeInformation)
                            txtBizUnitTestDetail.Text = PrettyPrintXML (nodeInfo.xmlDoc).ToString
                        Else
                            Dim bizUnitInfo As BizUnitInformation = DirectCast (node.Tag, BizUnitInformation)
                            Dim xmlDoc As New XmlDocument
                            xmlDoc.LoadXml (bizUnitInfo.testScriptNode.OuterXml.ToString)

                            txtBizUnitTestDetail.Text = PrettyPrintXML (xmlDoc).ToString
                        End If
                    End If
                End If
            Catch ex As IOException
                Common.LogError (ex.Message, chkDisplayErrors.Checked)
            Finally
                txtBizUnitTestDetail.ReadOnly = True
                editMode = False
                tsLabel2.Text = String.Empty
                m_IsDirty = False
            End Try
        End If
    End Sub

    Private Sub txtBizUnitTestDetail_MouseClick (ByVal sender As Object, ByVal e As MouseEventArgs) _
        Handles txtBizUnitTestDetail.MouseClick
        Select Case e.Button
            Case System.Windows.Forms.MouseButtons.Right
                Dim p As Point
                p = New Point (e.X, e.Y)
                If tabOutput.SelectedTab Is tabTestDetail Then
                    contextMenuEdit.Visible = True
                    contextMenuCopy.Visible = True
                    contextMenuSave.Visible = False
                    contextMenuRun.Visible = False
                    contextMenuSeparator1.Visible = False
                    contextMenuRunAll.Visible = False
                    ctxMnuEdit.Show (Me, p)
                End If
        End Select
    End Sub

    ''' <summary>
    ''' If chkAutoScroll is checked then automatically scroll to end of text box
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub txtOutput_TextChanged (ByVal sender As Object, ByVal e As EventArgs) _
        Handles txtBizUnitTestDetail.TextChanged, txtBizUnitTestResult.TextChanged
        If chkAutoScroll.Checked Then txtBizUnitTestResult.ScrollToCaret()
        If Not txtBizUnitTestDetail.ReadOnly And tabOutput.SelectedTab Is tabTestDetail Then m_IsDirty = True
    End Sub

#End Region

#Region "Private Sub-Routines"

    Private Sub BizUnit_RunTest()
        Dim bizUnit As BizUnit
        Try
            txtBizUnitTestDetail.ReadOnly = True
            EnableControls (False)
            bizUnit = New BizUnit (smokeTestNode.FullPath)
            bizUnit.RunTest()
            UpdateNodeStatus (smokeTestNode)
            EnableControls (True)
            UpdateStatusLabel ("Finished", 1)
        Catch ex As Exception
            Call TextWriter_Results (Me, New XMLEventArgs (ex.Message.ToString))
            UpdateImageIndex (smokeTestNode, FormImages.Failed)
            Common.LogError (ex.Message.ToString, chkDisplayErrors.Checked, Common.formCaption, MessageBoxIcon.Error)
            EnableControls (True)
        Finally
            smokeTestNode = Nothing
            bizUnit = Nothing
        End Try
    End Sub

    Private Sub ChangeTab (ByVal newTab As TabPage)
        If tabOutput.InvokeRequired Then
            tabOutput.Invoke (New ChangeTab1 (AddressOf ChangeTab), New Object() {newTab})
        Else
            tabOutput.SelectedTab = newTab
        End If
    End Sub

    Private Sub EnableControls (ByVal value As Boolean)
        If Me.InvokeRequired Then _
            : Me.Invoke (New GenericSingleBooleanDelegate (AddressOf EnableControls), New Object() {value})
        Else
            For Each ctrl As Control In Me.Controls
                If _
                    Not TypeOf (ctrl) Is CheckBox And Not TypeOf (ctrl) Is RichTextBox And _
                    Not TypeOf (ctrl) Is SplitContainer Then ctrl.Enabled = value
            Next

            If value Then
                If GetSelectedNodeIsXMLTest() Then
                    btnRunAll.Enabled = False
                    btnRunTest.Enabled = Not btnRunAll.Enabled
                Else
                    If Not CheckIfNodeIsChildOfTest (GetSelectedNode) Then
                        btnRunAll.Enabled = True
                        btnRunTest.Enabled = Not btnRunAll.Enabled
                    Else
                        btnRunAll.Enabled = False
                        btnRunTest.Enabled = False
                    End If
                End If
            End If
        End If
    End Sub

    Private Sub EmptyNodeResults (ByVal smokeTestNode As TreeNode)

        If tvSmokeTests.InvokeRequired Then
            tvSmokeTests.Invoke (New GenericSingleTreeNodeDelegate (AddressOf EmptyNodeResults), _
                                 New Object() {smokeTestNode})
        Else
            If smokeTestNode.Text.Contains (".xml") Then
                If smokeTestNode.Tag Is Nothing Then LoadTestDefinition (smokeTestNode)
                Dim nodeInfo As NodeInformation = DirectCast (smokeTestNode.Tag, NodeInformation)

                nodeInfo.testResults = Nothing
                smokeTestNode.Tag = nodeInfo

                smokeTestNode.ImageIndex = FormImages.Script
                smokeTestNode.SelectedImageIndex = FormImages.Script
            End If

            For Each node As TreeNode In smokeTestNode.Nodes
                If node.Text.Contains (".xml") Then
                    Dim nodeInfo As BizUnitInformation = DirectCast (node.Tag, BizUnitInformation)
                    nodeInfo.testResults = Nothing
                    node.Tag = nodeInfo
                    node.ImageIndex = FormImages.Script
                    node.SelectedImageIndex = FormImages.Script
                End If

                If node.Nodes.Count > 0 Then EmptyNodeResults (node)
            Next
        End If
    End Sub

    Private Sub ExpandAllNodes (ByVal node As TreeNode)
        If tvSmokeTests.InvokeRequired Then
            tvSmokeTests.Invoke (New GenericSingleTreeNodeDelegate (AddressOf ExpandAllNodes), New Object() {node})
        Else
            node.ExpandAll()
        End If
    End Sub

    Private Sub LoadRegistryValues()
        sourceSmokeTestPath = Common.ReadRegistry ("SourcePath")
        chkDisplayErrors.Checked = ReturnBooleanValueFromString (Common.ReadRegistry ("DisplayErrors"))
        chkAutoScroll.Checked = ReturnBooleanValueFromString (Common.ReadRegistry ("AutoScroll"))
    End Sub

    Private Sub LoadSettings()

        tvSmokeTests.Nodes.Clear()

        LoadRegistryValues()

        If sourceSmokeTestPath.Trim = String.Empty Then
            tsSave.Enabled = False
            tsCopy.Enabled = False
            tsClear.Enabled = False
            tsRefresh.Enabled = False
            tsLabel1.Text = "Please load some BizUnit tests!"
        Else : LoadTreeView()
        End If

    End Sub

    Private Sub LoadTestDefinition (ByVal currentNode As TreeNode)
        Dim xmlDoc As XmlDocument

        Try
            If File.Exists (currentNode.FullPath) Then
                If currentNode.Nodes.Count > 0 Then
                    For i As Integer = 0 To currentNode.Nodes.Count - 1
                        currentNode.Nodes.RemoveAt (0)
                    Next
                End If

                xmlDoc = New XmlDocument

                xmlDoc.Load (currentNode.FullPath)

                Dim nodeInfo As New NodeInformation

                nodeInfo.xmlDoc = xmlDoc
                nodeInfo.testResults = New StringBuilder
                nodeInfo.testResults.Append (noXMLResults)
                currentNode.Tag = nodeInfo

                txtBizUnitTestDetail.Text = PrettyPrintXML (xmlDoc).ToString
                Dim testSetup As New TreeNode (testSetupKey)

                Dim bizUnitInfo As New BizUnitInformation

                For Each xmlTestSetupNode As XmlNode In xmlDoc.SelectNodes ("./TestCase/TestSetup")
                    bizUnitInfo.testScriptNode = xmlTestSetupNode
                    bizUnitInfo.testResults = New StringBuilder
                    bizUnitInfo.testResults.Append (noXMLResults)
                    testSetup.Tag = bizUnitInfo
                    For Each childXMLNode As XmlNode In xmlTestSetupNode.ChildNodes
                        If childXMLNode.Attributes IsNot Nothing Then
                            Dim childNode As New TreeNode (childXMLNode.Attributes.GetNamedItem ("typeName").Value)

                            bizUnitInfo = New BizUnitInformation
                            bizUnitInfo.testScriptNode = childXMLNode
                            bizUnitInfo.testResults = New StringBuilder
                            bizUnitInfo.testResults.Append (noXMLResults)

                            childNode.Tag = bizUnitInfo
                            testSetup.Nodes.Add (childNode)
                        End If
                    Next
                Next

                Dim testExecution As New TreeNode (testExecutionKey)

                For Each xmlTestExecutionNode As XmlNode In xmlDoc.SelectNodes ("./TestCase/TestExecution")
                    bizUnitInfo.testScriptNode = xmlTestExecutionNode
                    bizUnitInfo.testResults = New StringBuilder
                    bizUnitInfo.testResults.Append (noXMLResults)
                    testExecution.Tag = bizUnitInfo
                    For Each childXMLNode As XmlNode In xmlTestExecutionNode.ChildNodes
                        If childXMLNode.Attributes IsNot Nothing Then
                            Dim childNode As New TreeNode (childXMLNode.Attributes.GetNamedItem ("typeName").Value)

                            bizUnitInfo = New BizUnitInformation
                            bizUnitInfo.testScriptNode = childXMLNode
                            bizUnitInfo.testResults = New StringBuilder
                            bizUnitInfo.testResults.Append (noXMLResults)

                            childNode.Tag = bizUnitInfo
                            testExecution.Nodes.Add (childNode)
                        End If
                    Next
                Next

                Dim testCleanUp As New TreeNode (testCleanUpKey)

                For Each xmlTestCleanUpNode As XmlNode In xmlDoc.SelectNodes ("./TestCase/TestCleanup")
                    bizUnitInfo.testScriptNode = xmlTestCleanUpNode
                    bizUnitInfo.testResults = New StringBuilder
                    bizUnitInfo.testResults.Append (noXMLResults)
                    testCleanUp.Tag = bizUnitInfo
                    For Each childXMLNode As XmlNode In xmlTestCleanUpNode.ChildNodes
                        If childXMLNode.Attributes IsNot Nothing Then
                            Dim childNode As New TreeNode (childXMLNode.Attributes.GetNamedItem ("typeName").Value)

                            bizUnitInfo = New BizUnitInformation
                            bizUnitInfo.testScriptNode = childXMLNode
                            bizUnitInfo.testResults = New StringBuilder
                            bizUnitInfo.testResults.Append (noXMLResults)

                            childNode.Tag = bizUnitInfo
                            testCleanUp.Nodes.Add (childNode)
                        End If
                    Next
                Next

                currentNode.Nodes.Add (testSetup)
                currentNode.Nodes.Add (testExecution)
                currentNode.Nodes.Add (testCleanUp)
            Else
                Common.LogError ("File does not exist: " & currentNode.FullPath, chkDisplayErrors.Checked)
                Exit Sub
            End If

        Catch ex As XmlException
            txtBizUnitTestDetail.Clear()
            Common.LogError (ex.Message.ToString (CultureInfo.InvariantCulture), chkDisplayErrors.Checked)
        End Try

    End Sub

    Private Sub LoadTreeView()
        Dim directory As DirectoryInfo

        If Not String.IsNullOrEmpty (sourceSmokeTestPath) Then
            Dim testPaths As String() = sourceSmokeTestPath.Split (CChar (";"))

            For i As Integer = 0 To testPaths.Length - 1
                If testPaths (i) <> String.Empty Then
                    directory = New DirectoryInfo (testPaths (i))
                    If (directory.Exists()) Then
                        Dim rootNode As New TreeNode (testPaths (i))

                        For Each s As DirectoryInfo In directory.GetDirectories()
                            Dim node As New TreeNode (s.Name)
                            Dim childDirectory As New DirectoryInfo (s.FullName)

                            For Each f As FileInfo In childDirectory.GetFiles (xmlFileSearchPattern)
                                Dim childNode As New TreeNode (f.Name)
                                node.Nodes.Add (childNode)
                            Next

                            'Only add node if tests exist for message type.
                            If node.Nodes.Count > 0 Then rootNode.Nodes.Add (node)
                        Next

                        For Each f As FileInfo In directory.GetFiles (xmlFileSearchPattern)
                            Dim childNode As New TreeNode (f.Name)
                            rootNode.Nodes.Add (childNode)
                        Next

                        tvSmokeTests.Nodes.Add (rootNode)

                        rootNode.Expand()
                    Else _
                        : Common.LogError ("Directory doesn't exist! Please check your settings and reload application.", _
                                           chkDisplayErrors.Checked)
                    End If
                End If
                tvSmokeTests.Refresh()
            Next
        End If
    End Sub

    Private Sub RunTest()
        If GetSelectedNode() IsNot Nothing Then
            smokeTestNode = GetSelectedNode()
            smokeTestNode.ExpandAll()

            EmptyNodeResults (smokeTestNode)

            smokeTestLevel = TestLevel.None
            smokeTestStepNode = - 1

            If File.Exists (smokeTestNode.FullPath) Then
                UpdateOutputText ("")
                UpdateStatusLabel ("Running: " & smokeTestNode.FullPath, 1)

                bgTestRunner.RunWorkerAsync()

            Else : Common.LogError ("File does not exist, please refresh your test list", chkDisplayErrors.Checked)
            End If
        Else : Common.LogError ("Please highlight a test", chkDisplayErrors.Checked)
        End If
    End Sub

    Private Sub RunAllTests()
        If GetSelectedNode() IsNot Nothing Then
            smokeTestNode = GetSelectedNode()

            ExpandAllNodes (smokeTestNode)
            EmptyNodeResults (smokeTestNode)

            smokeTestLevel = TestLevel.None
            smokeTestStepNode = - 1

            If File.Exists (smokeTestNode.FullPath) Then
                UpdateOutputText ("")
                UpdateStatusLabel ("Running: " & smokeTestNode.FullPath, 1)
                BizUnit_RunTest()
            Else _
                : Common.LogError ("File does not exist, please refresh your smoke test list", chkDisplayErrors.Checked)
            End If
        Else : Common.LogError ("Please highlight a smoke test", chkDisplayErrors.Checked)
        End If
    End Sub

    Private Sub RunAllSmokeTests()
        RunAllSmokeTests (GetSelectedNode)
    End Sub

    Private Sub RunAllSmokeTests (ByVal node As TreeNode)

        For Each childNode As TreeNode In node.Nodes
            If Not childNode.Text.Contains (".xml") Then
                If childNode.Nodes.Count > 0 Then RunAllSmokeTests (childNode)
            ElseIf childNode.Text.Contains (".xml") Then
                SetChildNode (childNode)
                RunAllTests()
            End If
        Next

        'testsRunning = False

    End Sub

    Private Sub SaveReport (ByVal node As TreeNode)
        Dim filePath As String = node.FullPath
        Dim indexOf As Integer = filePath.LastIndexOf ("\", StringComparison.OrdinalIgnoreCase) + 1

        If resultsFolder = String.Empty Then
            Dim fbd As New FolderBrowserDialog

            With fbd
                .Description = "Please select a fodler in which to save the results"
                .ShowNewFolderButton = True
                If .ShowDialog (Me) = System.Windows.Forms.DialogResult.OK Then
                    resultsFolder = fbd.SelectedPath.ToString & "\"
                Else
                    Common.LogError ("You must set a folder as the results folder", chkDisplayErrors.Checked)
                    Exit Sub
                End If
            End With
            fbd = Nothing
        End If

        Dim nodeinfo As NodeInformation = DirectCast (node.Tag, NodeInformation)

        If nodeinfo.testResults IsNot Nothing Then
            If nodeinfo.testResults.ToString <> noXMLResults Then
                Dim _
                    imageKey As FormImages = _
                        DirectCast ([Enum].Parse (GetType (FormImages), node.ImageIndex.ToString), FormImages)
                Dim result As String = imageKey.ToString().ToUpper (CultureInfo.InvariantCulture)

                Dim _
                    fileName As String = resultsFolder & result & "_" & _
                                         DateTime.Now.ToString ("hhmmss", CultureInfo.InvariantCulture) & "_" & _
                                         filePath.Substring (indexOf, filePath.Length - (indexOf))
                fileName = fileName.Replace (".xml", ".log")
                Dim swOut As StreamWriter
                Try
                    swOut = New StreamWriter (fileName)
                    swOut.Write (nodeinfo.testResults.ToString)
                    swOut.Close()
                Catch ex As IOException
                    Common.LogError ("Failed to save file: " & fileName & " - " & ex.Message.ToString, _
                                     chkDisplayErrors.Checked)
                Finally
                    swOut = Nothing
                End Try
            End If
        End If
    End Sub

    Private Sub SaveXMLToFile (ByVal smokeTestNode As TreeNode, ByVal newChild As XmlNode, ByVal oldChild As XmlNode)
        If Not smokeTestNode.Text.Contains (".xml") Then _
            Throw _
                New ArgumentOutOfRangeException ("smokeTestNode", smokeTestNode.Level, _
                                                 "Invalid smokeTestNode, this should be a level 2 node")

        Dim filePath As String = smokeTestNode.FullPath

        If File.Exists (filePath) Then 'Double Check to be sure
            If File.GetAttributes (filePath) = FileAttributes.ReadOnly Then
                Common.LogError ( _
                                 "Cannot save file: " & filePath & vbNewLine & _
                                 " because it has an attribute of Read-Only. Please change this and try to save again.", _
                                 chkDisplayErrors.Checked)
            End If
        End If

        Dim xmlDoc As XmlDocument
        Dim nodeInfo As NodeInformation = DirectCast (smokeTestNode.Tag, NodeInformation)
        xmlDoc = nodeInfo.xmlDoc

        Dim updatedNode As Boolean
        For Each childNode As XmlNode In xmlDoc.ChildNodes
            For Each grandChild As XmlNode In childNode.ChildNodes
                If grandChild.Equals (oldChild) Then
                    grandChild.InnerXml = newChild.InnerXml
                    updatedNode = True
                    Exit For
                Else
                    For Each greatGrandChild As XmlNode In grandChild.ChildNodes
                        If greatGrandChild.Equals (oldChild) Then
                            greatGrandChild.InnerXml = newChild.InnerXml
                            updatedNode = True
                            Exit For
                        End If
                    Next
                    If updatedNode Then Exit For
                End If
            Next
            If updatedNode Then Exit For
        Next

        Try
            xmlDoc.Save (filePath)

            LoadTestDefinition (smokeTestNode)
        Catch ex As IOException
            Common.LogError (ex.Message.ToString(), chkDisplayErrors.Checked)
        Finally
            xmlDoc = Nothing
        End Try
    End Sub

    Private Sub SetChildNode (ByVal childNode As TreeNode)
        If tvSmokeTests.InvokeRequired Then
            tvSmokeTests.Invoke (New GenericSingleTreeNodeDelegate (AddressOf SetChildNode), New Object() {childNode})
        Else : tvSmokeTests.SelectedNode = childNode
        End If
    End Sub

    Private Sub UpdateImageIndex (ByVal testStepNode As TreeNode, ByVal index As FormImages)
        'Ugly Code PLEASE UPDATE ME
        If testStepNode IsNot Nothing Then
            If tvSmokeTests.InvokeRequired Then
                tvSmokeTests.Invoke (New UpdateImageIndex1 (AddressOf UpdateImageIndex), _
                                     New Object() {testStepNode, index})
            Else
                If _
                    testStepNode.ImageIndex <> FormImages.Failed And testStepNode.ImageIndex <> FormImages.Intermediate And _
                    testStepNode.ImageIndex <> FormImages.Success Then
                    testStepNode.ImageIndex = index
'Update current node
                    testStepNode.SelectedImageIndex = index
                End If

                If testStepNode.Parent IsNot Nothing Then UpdateParentImageIndex (testStepNode.Parent, index)
            End If
        End If
    End Sub

    Private Sub UpdateNodeStatus (ByVal node As TreeNode)
        If tvSmokeTests.InvokeRequired Then
            tvSmokeTests.Invoke (New GenericSingleTreeNodeDelegate (AddressOf UpdateNodeStatus), New Object() {node})
        Else
            node.ImageIndex = FormImages.Success
            node.Collapse()
            For Each childnode As TreeNode In node.Nodes
                If childnode.ImageIndex = FormImages.Failed Then
                    node.ImageIndex = FormImages.Failed
                    node.SelectedImageIndex = FormImages.Failed
                    node.Expand()
                    Exit For
                End If
            Next
        End If
    End Sub

    Private Sub UpdateStatusLabel (ByVal value As String, ByVal index As Integer)
        Select Case index
            Case 1 : tsLabel1.Text = value
            Case 2 : tsLabel2.Text = value
            Case 3 : tslabel3.Text = value
        End Select
    End Sub

    Private Sub UpdateOutputText (ByVal value As String)
        If txtBizUnitTestDetail.InvokeRequired Then _
            : txtBizUnitTestDetail.Invoke (New UpdateOutputText1 (AddressOf UpdateOutputText), New Object() {value})
        Else : txtBizUnitTestResult.Text = value
        End If
    End Sub

    Private Sub UpdateParentImageIndex (ByVal parentNode As TreeNode, ByVal index As FormImages)
        If parentNode Is Nothing Then Throw New ArgumentException ("parentNode cannot be null")

        Select Case index
            Case FormImages.Failed
                parentNode.ImageIndex = index
                parentNode.SelectedImageIndex = index
            Case FormImages.Intermediate
                If parentNode.ImageIndex <> FormImages.Failed Then
                    parentNode.SelectedImageIndex = FormImages.Intermediate
                    parentNode.ImageIndex = FormImages.Intermediate
                End If
            Case FormImages.Success
                If parentNode.ImageIndex <> FormImages.Failed And parentNode.ImageIndex <> FormImages.Intermediate Then
                    parentNode.ImageIndex = index
                    parentNode.SelectedImageIndex = index
                End If
            Case FormImages.Running
                If parentNode.ImageIndex <> FormImages.Failed And parentNode.ImageIndex <> FormImages.Intermediate Then
                    If parentNode.ImageIndex = FormImages.Success And smokeTestLevel = TestLevel.CleanUp Then _
                        Exit Select
                    parentNode.ImageIndex = index
                    parentNode.SelectedImageIndex = index
                End If
        End Select

        If parentNode.Parent IsNot Nothing Then UpdateParentImageIndex (parentNode.Parent, index)

    End Sub

    Private Sub UpdateTestNode (ByVal testNode As TreeNode, ByVal result As String)
        Dim bizUnitInfo As BizUnitInformation

        If testNode IsNot Nothing Then
            UpdateImageIndex (testNode, FormImages.Running)
            If testNode.Tag Is Nothing Then
                bizUnitInfo = New BizUnitInformation
                bizUnitInfo.testResults.Append (result)
            Else
                bizUnitInfo = DirectCast (testNode.Tag, BizUnitInformation)
                If bizUnitInfo.testResults Is Nothing Then : bizUnitInfo.testResults = New StringBuilder
                ElseIf bizUnitInfo.testResults.ToString = noXMLResults Then _
                    : bizUnitInfo.testResults = New StringBuilder
                End If
                bizUnitInfo.testResults.AppendLine (result)
            End If

            testNode.Tag = bizUnitInfo

            If result.Contains ("Step:") And result.Contains ("started @") Then
                If smokeTestStepNode = - 1 Then
                    errorCaught = False
                    smokeTestStepNode = 0
                End If
            End If

            If smokeTestStepNode >= 0 Then UpdateTestChildNode (testNode, result)
        End If
    End Sub

    Private Sub UpdateTestChildNode (ByVal parentTestNode As TreeNode, ByVal result As String)
        Dim bizUnitInfo As BizUnitInformation
        Dim testStepNode As TreeNode = Nothing

        If smokeTestLevel = TestLevel.CleanUp Then
            If smokeTestStepNode < parentTestNode.Nodes.Count Then _
                testStepNode = parentTestNode.Nodes (smokeTestStepNode)
        Else
            testStepNode = parentTestNode.Nodes (smokeTestStepNode)
        End If

        If testStepNode IsNot Nothing Then
            UpdateImageIndex (testStepNode, FormImages.Running)
        End If

        If result.Contains ("Error: Exception caught!") Then
            errorCaught = False
            If Not FailOnError (testStepNode) Then
                UpdateImageIndex (testStepNode, FormImages.Intermediate)
            Else
                UpdateImageIndex (testStepNode, FormImages.Failed)
            End If
        End If

        If result.Contains ("Step:") And result.Contains ("ended @") Then
            If Not errorCaught Then UpdateImageIndex (testStepNode, FormImages.Success)
            smokeTestStepNode += 1
        End If

        If testStepNode IsNot Nothing Then
            If testStepNode.Tag Is Nothing Then
                bizUnitInfo = New BizUnitInformation
                bizUnitInfo.testResults.Append (result)
            Else
                bizUnitInfo = DirectCast (testStepNode.Tag, BizUnitInformation)
                If bizUnitInfo.testResults Is Nothing Then : bizUnitInfo.testResults = New StringBuilder
                ElseIf bizUnitInfo.testResults.ToString = noXMLResults Then _
                    : bizUnitInfo.testResults = New StringBuilder
                End If
                bizUnitInfo.testResults.AppendLine (result)
            End If

            testStepNode.Tag = bizUnitInfo
        End If

    End Sub

#End Region

#Region "Private Functions"

    Private Function CheckIfNodeIsChildOfTest (ByVal node As TreeNode) As Boolean
        Dim retVal As Boolean

        If node.Parent IsNot Nothing Then
            If node.Parent.Text.Contains (".xml") Then : retVal = True
            Else : If node.Parent IsNot Nothing Then retVal = CheckIfNodeIsChildOfTest (node.Parent)
            End If
        End If

        CheckIfNodeIsChildOfTest = retVal
    End Function

    ''' <summary>
    ''' Accepts in an XMLDocument and returns a stringWriter containing indented (Pretty Formateed) XML
    ''' </summary>
    ''' <param name="xmlDoc"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function PrettyPrintXML (ByVal xmlDoc As XmlDocument) As StringWriter
        Dim stringWriter As New StringWriter (CultureInfo.InvariantCulture)

        If xmlDoc IsNot Nothing Then
            Dim xmlReader As New XmlNodeReader (xmlDoc)
            Dim xmlWriter As New XmlTextWriter (stringWriter)

            With xmlWriter
                .Formatting = Formatting.Indented
                .Indentation = 1
                .WriteNode (xmlReader, True)
            End With
        End If

        Return stringWriter

    End Function

    ''' <summary>
    ''' Checks for the failOnError attribute on a test script node and returns its value
    ''' </summary>
    ''' <param name="testScriptNode"></param>
    ''' <returns>Boolean</returns>
    ''' <remarks></remarks>
    Private Function FailOnError (ByVal testScriptNode As TreeNode) As Boolean
        Dim retVal As Boolean

        If testScriptNode.Tag IsNot Nothing Then
            Dim bizUnitInfo As BizUnitInformation = DirectCast (testScriptNode.Tag, BizUnitInformation)
            Dim xmlNode As XmlNode = bizUnitInfo.testScriptNode

            Try
                If xmlNode.Attributes.Count > 0 Then
                    Dim xmlAttr As XmlAttribute
                    xmlAttr = xmlNode.Attributes ("failOnError")

                    If xmlAttr IsNot Nothing Then : retVal = CType (xmlNode.Attributes ("failOnError").Value, Boolean)
                    Else : retVal = True
                    End If
                End If
            Catch ex As XmlException : Common.LogError (ex.Message.ToString, False)
            Finally : xmlNode = Nothing
            End Try
        End If

        Return retVal

    End Function

    ''' <summary>
    ''' Finds the smoke test node (Level 2)
    ''' </summary>
    ''' <param name="node"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function FindSmokeTestNodeFromChildNode (ByVal node As TreeNode) As TreeNode
        If Not node.Text.Contains (".xml") Then
            If CheckIfNodeIsChildOfTest (node) Then : Return FindSmokeTestNodeFromChildNode (node.Parent)
            Else _
                : Throw New ArgumentOutOfRangeException ("node", node.Level, "You can only pass a child node of a test.")
            End If
        End If

        Return node

    End Function

    ''' <summary>
    ''' Returns the currently selected node from the treeview
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetSelectedNode() As TreeNode
        If tvSmokeTests.InvokeRequired Then _
            : Return DirectCast (tvSmokeTests.Invoke (New GetSelectedNode1 (AddressOf GetSelectedNode)), TreeNode)
        Else
            If smokeTestNode IsNot Nothing Then : Return smokeTestNode
            Else : Return tvSmokeTests.SelectedNode
            End If
        End If
    End Function

    Private Function GetSelectedNodeIsXMLTest() As Boolean
        If GetSelectedNode() IsNot Nothing Then Return GetSelectedNode.Text.Contains (".xml")
    End Function

    ''' <summary>
    ''' Returns the Read-Only attribute of a file
    ''' </summary>
    ''' <param name="filePath"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function IsFileReadOnly (ByVal filePath As String) As Boolean
        If File.Exists (filePath) Then
            If File.GetAttributes (filePath) = FileAttributes.ReadOnly Then
                Common.LogError( _
                                 "Cannot save file: " & filePath & _
                                 " because it has an attribute of Read-Only. Please change this and try to save again.", _
                                 True)
                IsFileReadOnly = True
                Exit Function
            End If
        End If

        IsFileReadOnly = False
    End Function

    Private Function ReturnBooleanValueFromString (ByVal value As String) As Boolean
        Dim retVal As Boolean

        If value = "1" Or value.ToUpper (CultureInfo.InvariantCulture) = "TRUE" Then retVal = True

        Return retVal

    End Function

#End Region

    Private Sub bgTestRunner_DoWork (ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bgTestRunner.DoWork
        testsRunning = True
        ChangeTab (tabTestResult)
        Select Case testType
            Case RunTestType.All : RunAllSmokeTests()
            Case RunTestType.Single : BizUnit_RunTest()
        End Select
    End Sub

    Private Sub bgTestRunner_RunWorkerCompleted (ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
        Handles bgTestRunner.RunWorkerCompleted
        testsRunning = False
        smokeTestNode = Nothing
        tsLabel1.Text = "Test(s) Complete"
    End Sub
End Class
